import axios from 'axios'
// import router from '../../router'
import { ElMessage, ElMessageBox,  ElNotification } from 'element-plus'
import { debounce } from 'lodash'

let loading = null
const lockMap = new Map()
let msgBoxObj = null

const getCookie = key => {
  const arr = document.cookie.split(';').map(it => it.trim()).filter(it => it.split('=')[0] === key)
  if (arr.length) {
    return arr[0].split('=')[1]
  } else {
    return ''
  }
}

const compareCookie = key => {
  const newVal = getCookie(key)
  const oldVal = window.cookieMap !==undefined ? window.cookieMap.get(key) || '' : ''
  return newVal === oldVal
}

export default {
  systemTimeOffset: 0,
  baseUrl: '',
  defaultNoData() {
    ElMessageBox.alert('暂无数据', '警告', { type: 'warning' })
  },
  openLoading() {
  },
  closeLoading() {
  },
  addNotify(key, notifyOptions) {
    if (!notifyOptions) {
      lockMap.set(key, key)
      return
    }
    const options = {
      // title: '提示',
      message: '数据处理中',
      duration: 0,
      position: 'bottom-right'
    }
    if (typeof notifyOptions === 'string') {
      options.message = notifyOptions
    } else if (typeof notifyOptions === 'function') {
      const opt = notifyOptions.call(arguments)
      if (opt) {
        if (typeof opt === 'string') {
          options.message = opt
        } else if (typeof opt === 'object') {
          Object.assign(options, notifyOptions)
        }
      }
    } else if (typeof notifyOptions === 'object') {
      Object.assign(options, notifyOptions)
    }
    // console.log(key, options)
    lockMap.set(key, ElNotification(options))
  },
  hasNotify(key) {
    // console.log(`lockMap.has(${key}): ${lockMap.has(key)}`)
    if (lockMap.has(key)) {
      ElMessage.warning('数据正在处理中，请勿重复触发')
      return true
    }
    return false
  },
  closeNotify(key) {
    // console.log(`closeNotify(${key})`)
    if (lockMap.has(key)) {
      const value = lockMap.get(key)
      value !== key && lockMap.get(key).close()
      lockMap.delete(key)
    }
  },
  defaultErrorDeal(error) {
    const _t = this
    console.error(error)
    const dealNetworkError = function(error, msg) {
      if (error.response && error.response.status && error.response.status != 200) {
        msg.msg = 'HTTP ' + error.response.status
      }
    }
    const dealBusinessError = function(error, msg) {
      if (error.response && error.response.data) {
        if (error.response.data.error) {
          msg.code = error.response.data.error.code
        }
        if (error.response.data.msg && error.response.data.msg.content) {
          msg.msg = error.response.data.msg.content
        }
        if (error.response.data.msg && error.response.data.msg.msgType) {
          msg.msgType = error.response.data.msg.msgType
        }
      }
    }
    const errorMsg = { msg: '', msgType: 1 }
    dealNetworkError(error, errorMsg)
    dealBusinessError(error, errorMsg)
    if (!errorMsg.msg && !errorMsg.code) {
      return
    }
    const ms = []
    if (errorMsg.code) {
      ms.push(errorMsg.code)
    }
    if (errorMsg.msg) {
      ms.push(errorMsg.msg)
    }
    if (errorMsg.msgType == 2) {
      ElMessageBox.alert(errorMsg.msg, '错误', { type: 'error' })
    } else if (errorMsg.msgType == 3) {
      console.log('当前时间' + new Date() + ',后台Token超时')
      const isTokenTimeoutAlert = sessionStorage.getItem('isTokenTimeoutAlert')
      if (isTokenTimeoutAlert === 'false') {
        return
      }
      sessionStorage.setItem('isTokenTimeoutAlert', 'false')
      if (msgBoxObj) return
      msgBoxObj = ElMessageBox({
        title: '提示',
        type: 'warning',
        message: errorMsg.msg,
        confirmButtonText: '确定',
        callback: action => {
          msgBoxObj = null
          window.top.location.hash = '#/login/'
        }
      })
    } else {
      ElMessage.error(errorMsg.msg)
    }
  },
  trimData(data) {
    var ret = JSON.parse(JSON.stringify(data))
    var scanList = [ret]
    while (scanList.length > 0) {
      var obj = scanList[0]
      scanList = scanList.slice(1)
      for (var k in obj) {
        var typename = typeof (obj[k])
        if (typename == 'string') {
          obj[k] = obj[k].replace(/^\s+/, '').replace(/\s+$/, '')
          if (obj[k] == '') {
            delete obj[k]
          }
        }
        if (typename == 'object') {
          if (obj[k] == null) {
            delete obj[k]
          } else {
            scanList.push(obj[k])
          }
        }
      }
    }

    return ret
  },
  generalSuccess(response, successCallback, errorCallback) {
    successCallback(response)
  },
  doRequest(opt) {
    this.configRequest(opt)
  },
  getLock(opt) {
    const { lock } = opt
    let key
    let options
    switch (typeof lock) {
      case 'string':
        key = lock
        break
      case 'object':
        key = lock.key
        options = lock.options
        break
      case 'function':
        // eslint-disable-next-line no-case-declarations
        const fnRes = lock(arguments)
        switch (typeof fnRes) {
          case 'string':
            key = fnRes
            break
          case 'object':
            key = fnRes.key
            options = fnRes.options
            break
        }
        break
    }
    return { key, options }
  },
  configRequest(opt) {
    if (!opt || (Object.keys(opt).length === 1 && opt.loading)) { return }
    const { key, options } = this.getLock(opt)
    if (key && this.hasNotify(key)) return
    // defaults
    if (!opt.onError) { opt.onError = this.defaultErrorDeal }
    if (!opt.onSuccess) { opt.onSuccess = function() {} }
    // encodeURI get
    if (opt.method && opt.method.toLowerCase() === 'get' && opt.data) {
      const cs = []
      for (const k in opt.data) {
        cs.push(encodeURIComponent(k) + '=' + encodeURIComponent(opt.data[k]))
      }
      if (cs.length > 0) {
        opt.uri = opt.uri + '?' + cs.join('&')
      }
    }
    // double click prevent
    const setVal = function(opt, val) {
      let obj = null
      if (opt.disableField) {
        for (const idx in opt.disableField) {
          const dd = opt.disableField[idx]
          if (idx == 0) {
            obj = dd
          } 
        }
      }
    }
    setVal(opt, true)// 设置按钮状态为disabled
    key && this.addNotify(key, options)
    const checkGrey = debounce(function() {
      if (!compareCookie('grey')) {
        ElMessage({
          type: 'warning',
          message: '发现新版本，浏览器将在3秒后重新加载'
        })
        setTimeout(() => {
          window.top.location.reload()
        }, 3000)
      }
    }, 1000)
    return new Promise((resolve, reject) => {
      // do request
      this.request(opt.method, opt.uri, opt.data, opt.header).then(response => {
        setVal(opt, false)// 设置按钮状态为非disabled
        this.calcTimeOffset(response.data)
        opt.loading && this.closeLoading()
        key && this.closeNotify(key)
        this.generalSuccess(response, opt.onSuccess, opt.onError)
        checkGrey()
        resolve(response)
      }).catch(error => {
        setVal(opt, false)// 设置按钮状态为非disabled
        key && this.closeNotify(key)
        opt.onError(error)
        checkGrey()
        reject(error)
      })
    })
  },
  calcTimeOffset(data) {
    if (data && data.systemCurrentMills && data.systemCurrentMills > 1592482068362) {
      this.systemTimeOffset = data.systemCurrentMills - (new Date().getTime())
    }
  },
  request(method, url, data, header) {
    if (!header) { header = {} }

    return axios.request({
      method: method,
      headers: header,
      baseURL: this.baseUrl,
      url: url,
      data
    })
  },
}
